<?php
/**
 * Created by PhpStorm.
 * BuyUser: xl
 * Date: 16/11/11
 * Time: 11:28
 */
namespace common\widgets;

class BinaryDecimal {

    const DEFAULT_ALL_CLOSE_BIT = 562949953421311;

    //将一天的二进制时间转换为一个时间段数组
    public static function binaryToDecimal($dayTimeBit)
    {
        $flag = false;
        $each = array();
        $timeList = array();
        $num = 1;

        for ($i = 1; $i <= 49; $i ++)
        {
            if(($dayTimeBit & $num) == 0 && !$flag)
            {
                $flag = true;
                $tmp = $i / 2;
                $tmp = is_int($tmp) ? ($tmp - 1) . ":30" : floor($tmp) . ":00";
                $each['start'] = $tmp;
            }elseif(($dayTimeBit & $num) == $num && $flag) {
                $flag = false;
                $tmp = $i / 2;
                $tmp = is_int($tmp) ? ($tmp - 1) . ":30" : floor($tmp) . ":00";
                $each['end'] = $tmp;
                $timeList[] = $each;
                $each = [];
            }

            $num = $num << 1;

        }
        return $timeList;
    }

    //将一天的多个时间段转换为一个二进制时间
    public static function decimalToBinary($timeBit, $timeList)
    {
        foreach ($timeList as $row)
        {
            $startArr = explode(':', $row['time_start']);
            $endArr = explode(':', $row['time_end']);

            $check_time = self::checkFixTime($startArr, $endArr);

            if($check_time == false){
                return false;
            }

            $startPos = $startArr[1] == '30'
                ? $startArr[0] * 2 + 2
                : $startArr[0] * 2 + 1;

            $endPos = $endArr[1] == '30'
                ? $endArr[0] * 2 + 1
                : $endArr[0] * 2;

            for ($i = $endPos; $i >= $startPos; $i --)
            {
                $endBit = pow(2, $i - 1);
                $timeBit = $timeBit & (~$endBit);
            }
        }
        return $timeBit;
    }

	public static function timeBitFormatInfo($timeBit)
	{
		$timeBitFormat = [];

		if(empty($timeBit)){
			$timeBitFormat[1] = self::DEFAULT_ALL_CLOSE_BIT;
			$timeBitFormat[2] = self::DEFAULT_ALL_CLOSE_BIT;
			$timeBitFormat[3] = self::DEFAULT_ALL_CLOSE_BIT;
			$timeBitFormat[4] = self::DEFAULT_ALL_CLOSE_BIT;
			$timeBitFormat[5] = self::DEFAULT_ALL_CLOSE_BIT;
			$timeBitFormat[6] = self::DEFAULT_ALL_CLOSE_BIT;
			$timeBitFormat[7] = self::DEFAULT_ALL_CLOSE_BIT;
		}else{
			foreach($timeBit as $key=>$val){
				$timeBitFormat[$val['week']] = $val['time_bit'];
			}
		}

		return $timeBitFormat;
	}

	public static function timeBitFormatList($timeBit)
	{
		$timeBitFormat = [];

		if(!empty($timeBit)){
			foreach($timeBit as $key=>$val){
				$timeBitFormat[$val['time_execute']][$val['week']] = $val['time_bit'];
			}
		}

		return $timeBitFormat;
	}

    public static function checkTime($startArr, $endArr)
    {
        if(preg_match('/^[0-9]{1,2}$/',$startArr[0]) && preg_match('/^[0-9]{1,2}$/',$startArr[1]) && preg_match('/^[0-9]{1,2}$/',$endArr[0]) && preg_match('/^[0-9]{1,2}$/',$endArr[1]))
        {
            if($startArr[1] != "00" && $startArr[1] != "30"){
                return true;
            }
            if($startArr[0] < 0 || $startArr[0] > 24)
            {
                return true;
            }
            if($endArr[1] != '00' && $endArr[1] != '30'){
                return true;
            }
            if($endArr[0] < 0 || $endArr[0] > 24 )
            {
                return true;
            }
            if($startArr[0] > $endArr[0]){
                return true;
            }
            if(($startArr[0] == $endArr[0]) && ($startArr[1] >= $endArr[1])){
                return true;
            }
        }else{
            return true;
        }
    }

    public static function checkFixTime($startArr, $endArr)
    {
        if($startArr[1] != "00" && $startArr[1] != "30"){
            return false;
        }

        if($endArr[1] != '00' && $endArr[1] != '30'){
            return false;
        }

        if($startArr[0] > $endArr[0]){
            return false;
        }

        if(($startArr[0] == $endArr[0]) && ($startArr[1] > $endArr[1])){
            return false;
        }

        if(($startArr[0] == $endArr[0]) && ($startArr[1] == $endArr[1]) && (($startArr[1] != '00') || ($startArr[0] != '00'))){
            return false;
        }

        return true;
    }

    /**
     * @param $timeClass
     * @param $timeEnd
     * @return int|number
     * @author xl
     * 1代表有课,由课的开始结束时间，得到这节课的二进制字符串
     */
    public static function getClassBit($timeClass, $timeEnd)
    {
        $timeStr = date('H:i',$timeClass);
        $timeArr = explode(':', $timeStr);
        $index = 2*$timeArr[0] + ($timeArr[1] === '00' ? 0 : 1);
        $num = pow(2,$index);
        $num += ($timeEnd - $timeClass == 1500 ? 0 : pow(2,$index+1));
        return $num;
    }

    /**
     * @param $timeClass
     * @param $timeEnd
     * @author xl
     * 1代表有课
     */
    public static function getClassBitNew($timeClass, $timeEnd)
    {
        $startArr = explode(':',date('H:i',$timeClass));
        $endArr = explode(':',date('H:i',$timeEnd));

        $startPos = $startArr[1] >= 30 ? $startArr[0] * 2 + 1 : $startArr[0] * 2;

        if ($endArr[1] > 30)
        {
            $endPos = $endArr[0] * 2 + 1;
        }
        else
        {
            $endPos = $endArr[0] * 2;
        }

        $num = 0;
        for ($i=$startPos; $i <= $endPos; $i ++)
        {
            $num += pow(2,$i);
        }
        
        return $num;
    }

    /**
     * @param $time_start
     * @param $time_end
     * @return int|number
     * @author xl
     * 1代表请假
     */
    public static function getRestBit($time_start,$time_end)
    {
        $startStr = explode(':',date('H:i',$time_start));
        $endStr = explode(':',date('H:i',$time_end));
        $startPos = $startStr[1] == '30' ? $startStr[0] * 2 + 1 : $startStr[0] * 2;
        $endPos = $endStr[1] == '30' ? $endStr[0] * 2 + 1 : $endStr[0] * 2;

        $num = 0;
        for ($i=$startPos; $i < $endPos; $i ++)
        {
            $num += pow(2,$i);
        }

        return $num;
    }

    /**
     * 时间戳计算星期几
     * @param $week
     * @return int
     */
    public static function changeWeek($time)
    {
        $week = date('N', $time);
        return $week;
    }

    /**
     * 将钟点的字符串转化为当日的秒数
     * @param $start
     * @param $end
     * @author csj
     */
    public static function clockStrToSecond($start, $end)
    {
        $start_str = explode(':',$start);
        $end_str = explode(':',$end);
        $start_second = $start_str[0] * 3600 + $start_str[1] * 60;
        $end_second = $end_str[0] * 3600 + $end_str[1] * 60;

        return [$start_second, $end_second];
    }

	/**
	 * 将钟点的字符串转化为当日的分钟数
	 * @param $time
	 * @return float
	 * @author csj
	 */
	public static function clockStrToMinMinute($time)
	{
		$time_str = explode(':', $time);
		$time_minute = $time_str[0]*60 + intval($time_str[1]);
		return $time_minute;
	}


    /**
     * 将秒数转化为钟点小时格式
     * @param $start
     * @param $end
     * @author csj
     */
    public static function secondToClockStr($second=0)
    {
        if($second%60 == 0)
        {
            $result = intval($second/60) . ':00';
        }
        else
        {
            $result = intval($second/60) . ':' . ($second-(intval($second/60))*60);
        }
        return $result;
    }


    /**
     * 获取两个有序时间段数组的重叠时间
     * @param $intervals_1
     * @param $intervals_2
     * @return array
     * @author csj
     */
    public static function getIntervalArrayOverlap($intervals_1, $intervals_2, $type='yes')
    {
        $cur_1 = $cur_2 = 0;
        $overlapCount = 0;
        $overlap = [];

        while (($cur_1 < sizeof($intervals_1)) && ($cur_2 < sizeof($intervals_2)))
        {
            $curStart = max($intervals_1[$cur_1][0],$intervals_2[$cur_2][0]);

            if($intervals_1[$cur_1][1] < $intervals_2[$cur_2][1])
            {
                $curEnd = $intervals_1[$cur_1][1];
                $cur_1 += 1;
            }
            else
            {
                $curEnd = $intervals_2[$cur_2][1];
                $cur_2 += 1;
            }

            if($curStart < $curEnd){
                $overlapCount += $curEnd - $curStart;
                $overlap[] = [$curStart,$curEnd, 'type'=>$type];
            }
        }

        foreach($overlap as $key=>$val)
        {
            $overlap[$key]['start_time'] = self::secondToClockStr($val[0]);
            $overlap[$key]['end_time'] = self::secondToClockStr($val[1]);
        }

        return [
            'overlap_'.$type => $overlap,
            'overlap_'.$type.'_count' => $overlapCount,
        ];
    }

    /**
     * 获取有序时间段数组的不重叠时间 (0-24点)
     * @param $intervals_1
     * @return array
     * @author csj
     */
    public static function getIntervalArrayOverlapDiff($intervals)
    {
        $overlapNo = [];

        $startTime = 0;
        $endTime = 1440;

        $total = count($intervals);

        if(empty($intervals))
        {
            $overlapNo[] = [$startTime, $endTime];
        }
        else
        {
            foreach($intervals as $key=>$val)
            {
                if($key == 0)
                {
                    $overlapNo[] = [$startTime, $val[0]];
                }
                else
                {
                    $overlapNo[] = [$intervals[$key-1][1], $val[0]];
                }

                if($total == $key+1)
                {
                    $overlapNo[] = [$val[1], $endTime];
                }
            }
        }
        return $overlapNo;
    }

    /**
     * 获取两个有序时间段数组的重叠时间
     * @param $intervals_1  开放时间
     * @param $intervals_2  错误课表课程时间
     * @return array
     * @author csj
     */
    /*
    public static function getOverlapBySecond($intervals_1,$intervals_2)
    {
        $cur_1 = $cur_2 = $cur_3 = $cur_4 = 0;
        $overlapYesCount = $overlapNoCount = 0;
        $overlapYes = $overlapNo = [];

        //取重叠
        while (($cur_1 < sizeof($intervals_1)) && ($cur_2 < sizeof($intervals_2)) )
        {
            $curStart = max($intervals_1[$cur_1][0], $intervals_2[$cur_2][0]);

            if($intervals_1[$cur_1][1] < $intervals_2[$cur_2][1])
            {
                $curEnd = $intervals_1[$cur_1][1];
                $cur_1 += 1;
            }
            else
            {
                $curEnd = $intervals_2[$cur_2][1];
                $cur_2 += 1;
            }

            if($curStart < $curEnd){
                $overlapYes[] = [$curStart,$curEnd, 'type'=>'yes'];
            }
        }

        //取不重叠
        $change = 0;
        if(empty($overlapYes))
        {
            foreach($intervals_1 as $kn1=>$vn1)
            {
                $overlapNo[] = [$vn1[0], $vn1[1], 'type'=>'no'];
            }
        }
        else
        {
            while ( ($cur_3 < sizeof($intervals_1)) && ($cur_4 < sizeof($overlapYes)) )
            {
                if(count($intervals_1)==1 && count($overlapYes==1))
                {
                    if($intervals_1[$cur_3][1] > $overlapYes[$cur_4][1])
                    {
                        $overlapNo[] = [$overlapYes[$cur_4][1], $intervals_1[$cur_3][1], 'type'=>'no'];
                    }
                    $cur_3 +=1;
                    $cur_4 +=1;
                }
                else
                {
                    $curStart = min($intervals_1[$cur_3][0], $overlapYes[$cur_4][0]);

                    if($intervals_1[$cur_3][1] < $overlapYes[$cur_4][1])
                    {
                        if($change == 0){
                            $curEnd = $intervals_1[$cur_3][1];
                        }else{
                            $curStart = $overlapYes[$cur_4-1][1];
                            $curEnd = $intervals_1[$cur_3][1];
                            $change = 0;
                        }
                        $cur_3 += 1;
                    }
                    else
                    {
                        if($change == 0){
                            $curEnd = $overlapYes[$cur_4][0];
                            $change = 1;
                        }else{
                            $curStart = $overlapYes[$cur_4-1][1];
                            $curEnd = $overlapYes[$cur_4][0];
                        }
                        $cur_4 += 1;
                    }

                    if($curStart < $curEnd){
                        $overlapNo[] = [$curStart, $curEnd, 'type'=>'no'];
                    }
                }
            }
        }

        foreach($overlapYes as $key=>$val)
        {
            $overlapYes[$key]['start_time'] = self::secondToClockStr($val[0]);
            $overlapYes[$key]['end_time'] = self::secondToClockStr($val[1]);
            $overlapYesCount += ($val[1] - $val[0]);
        }

        foreach($overlapNo as $key=>$val)
        {
            $overlapNo[$key]['start_time'] = self::secondToClockStr($val[0]);
            $overlapNo[$key]['end_time'] = self::secondToClockStr($val[1]);
            $overlapNoCount += ($val[1] - $val[0]);
        }

        return [
            'overlap_no' => $overlapNo,
            'overlap_no_count' => $overlapNoCount,
            'overlap_yes' => $overlapYes,
            'overlap_yes_count' => $overlapYesCount,
        ];
    }
    */






    /**
     * @param $timeBit
     * @return int
     * @author xl
     * 计算时长，跟据二进制时间得到该时间的时长，多少个0返回多少个30分钟
     */
    public static function getFixLong($timeBit)
    {
        $long = 0;
        for ($i=1; $i<49; $i++)
        {
            $index = pow(2,$i-1);

            if (($timeBit & $index) == 0)
            {
                $long ++;
            }
        }

        return $long;
    }

    /**
     * @param $timeBit
     * @return int
     * @author xl
     * 计算时长，多少个1返回多少个30分钟
     */
    public static function getTimeLong($timeBit)
    {
        $long = 0;

        for ($i=1; $i<49; $i++)
        {
            $index = pow(2,$i-1);

            if (($timeBit & $index) == 1)
            {
                $long ++;
            }
        }

        return $long;
    }

    public static function getStudentFixTimeBit($timeHead, $timeFoot, $classType)
    {
        $index = 2*$timeHead + ($timeFoot === '00' ? 0 : 1);
        $num = pow(2,$index);
        $num += ($classType == 1 ? 0 : pow(2,$index+1));
        return $num;
    }
}